package module

import (
	"gogogo-server/engine/cororpc"
	"sync"
)

// IModule 模块职责
type IModule interface {
	OnInit() error    // 第一步所有模块的初始化,这一步只能模块自己初始化数据向
	AfterInit() error // 所有模块初始化后,继续初始化,这时候可以有模块间的简单交互
	OnDestroy()
	Run(closeSig chan bool)
	GetServerCoroRPC() *cororpc.RPCServer
}

// 模块包装
type moduleWrapper struct {
	mi       IModule
	closeSig chan bool
	wg       sync.WaitGroup
}

var modList []*moduleWrapper

func Register(mi IModule) {
	m := &moduleWrapper{
		mi:       mi,
		closeSig: make(chan bool),
	}
	modList = append(modList, m)
}

func Init() error {
	for _, m := range modList {
		if err := m.mi.OnInit(); err != nil {
			return err
		}
	}
	for _, m := range modList {
		if err := m.mi.AfterInit(); err != nil {
			return err
		}
	}
	for _, m := range modList {
		m.wg.Add(1)
		go run(m)
	}
	return nil
}

func run(m *moduleWrapper) {
	m.mi.Run(m.closeSig)
	m.wg.Done()
}

func Destroy() {
	for i := len(modList) - 1; i >= 0; i-- {
		modList[i].closeSig <- true
	}
	for _, m := range modList {
		m.wg.Wait()
		destroy(m)
	}
}

func destroy(m *moduleWrapper) {
	m.mi.OnDestroy()
}
